/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2025-02-06 09:43:58
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2025-02-08 14:54:56
 * @FilePath: /2024-4-20-pipe/yjl_test_pipe/process_pool/process_pool.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include<sys/wait.h>
#include"test.hpp"

using namespace std;

// master
class Channel
{
public:
    Channel(int wfd, int id, string &name)
        : _wfd(wfd), _childproid(id), _name(name)
    {
    }
    int get_wfd() {return _wfd;}
    pid_t get_id() {return _childproid;}
    string get_name() {return _name;}

    void close_channel()
    {
        close(_wfd);
    }

    void Wait()
    {
        pid_t rid=waitpid(_childproid,nullptr,0);
        if(rid>0)
        {
            cout<<"wait sucess,rid="<<rid<<endl;
        }
    }

    ~Channel()
    {
    }

private:
    int _wfd;
    pid_t _childproid;
    string _name;
};

// 子进程 work函数
void work(int rfd)
{
    while(true)
    {
        int command=0;
        int n=read(rfd,&command,sizeof(command));
        if(n==sizeof(int))
        {
            excute_task(command);
        }
    }
}

void create_pipe_child(int num,vector<Channel> *channels)
{
    for (int i = 0; i < num; i++)
    {
        // 1、创建管道
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if (n < 0)
            exit(-1);

        // 2、创建子进程
        pid_t id = fork();
        if (id == 0)
        {
            close(pipefd[1]);
            work(pipefd[0]);
            close(pipefd[0]);
            exit(0);
        }

        // 3、创建Channel的名字
        string channel_name = "   Channel -> " + to_string(i);

        // 父进程
        close(pipefd[0]);

        channels->push_back(Channel(pipefd[1], id, channel_name));
    }
}

int next_channel(int channel_num)
{
    static int next=0;
    int channel=next;
    next++;
    next%=channel_num;
    return channel;
}

void send_taskcommand(Channel &channel,int taskcommand)
{
    write(channel.get_wfd(),&taskcommand,sizeof(taskcommand));
}

void cleanup_channel(vector<Channel> &channels)
{
    for(auto &channel:channels)
    {
        channels.close_channel();

    }
    for(auto &channel:channels)
    {
        channels.Wait();
    }
}

// ./processpool 5（创建子进程的数目为5，argc应该=2）
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        cerr << "Usage:" << argv[0] << "processnum" << endl;
        return 1;
    }
    int num = stoi(argv[1]);

    loadtask();

    vector<Channel> channels;
    // 一、创建管道+子进程
    create_pipe_child(num,&channels);

    // 二、通过管道给子进程发送任务。

    // 1、选择一个任务
    int taskcommand=select_task();
    // 2、选择一个信道
    int channel_index=next_channel(channels.size());
    // 3、发送任务
    send_taskcommand(channels[channel_index],taskcommand);
    // 三、回收管道+子进程
    cleanup_channel(channels);

    return 0;
}